<template>
	<view :class="[`grid-gap-${props.gap}`, `grid-columns-${props.col * 2}`]" ref="xUploadsRef">
		<view class="images-item" :class="[props.type==='video'?`grid-column-${props.col * 2}`:'grid-column-2']"
			:style="{ height: props.type==='video'?`${height*2}px`:`${height}px` }" v-for="(temp, index) in tempList"
			:key="index">
			<image v-if="props.type === 'image'" :src="temp.url" mode="scaleToFill" class="bg-grey-6 rounded-4 w-p-100"
				:style="{ height: `${height}px` }" @tap="preview(index)" />
			<video v-else-if="props.type === 'video'" :src="temp.url" class="bg-grey-6 rounded-4 w-p-100"
				:style="{ height: `${height*2}px` }" />
			<view v-if="temp.error" class="error grid-gap-2">
				<text class="message fs-14">{{ temp.error }}</text>
				<text class="text-blue-1 fs-14" @tap="upload(index)">重试</text>
			</view>
			<uv-icon name="reload" color="#666" size="38" class="loading" v-if="temp.loading"></uv-icon>
			<view class="icons">
				<uv-icon name="close" color="#EA4545" v-if="!disbale" @tap="remove(index)"></uv-icon>
			</view>
		</view>
		<slot :height="height">
			<view class="bg-grey-6 rounded-4 flex flex-center flex-column grid-gap-2" :style="{ height: `${height}px` }"
				:class="[tempList.length > 0 || !props.fill ? 'grid-column-2' : `grid-column-${props.col * 2}`]"
				@tap="selected" v-if="tempList.length < props.limit">
				<uv-icon :name="props.placeholderIcon" size="38" color="#666"></uv-icon>
				<text class="text-grey fs-14">{{ props.placeholder }}</text>
				<text v-if="props.limit > 1" class="fs-14 font-weight-600 text-grey">
					{{ tempList.length }}/{{ props.limit }}
				</text>
			</view>
		</slot>
	</view>
</template>

<script setup>
	import { ref, watchEffect, defineProps, onMounted, nextTick } from 'vue';
	import { $http } from '@/utils';
	const props = defineProps({
		limit: {
			default: 1,
			type: Number
		},
		type: {
			default: 'image',
			type: String
		},
		col: {
			default: 3,
			type: Number
		},
		gap: {
			default: 3,
			type: Number
		},
		fill: {
			default: false,
			type: Boolean
		},
		autoUpload: {
			default: true,
			type: Boolean
		},
		margins: {
			default: 0,
			type: Number
		},
		data: {
			default: {
				is_hide: 1
			},
			type: Object
		},
		placeholder: {
			default: '选择照片',
			type: String
		},
		placeholderIcon: {
			default: 'photo-fill',
			type: String
		},
	})



	const tempList = ref([]);
	const height = ref(0);
	const emit = defineEmits(['update:modelValue', 'change']);
	watchEffect(() => {
		// if (Array.isArray(props.modelValue)) {
		// 	props.modelValue.forEach(item => {
		// 		if (typeof item === 'object') {
		// 			if (tempList.value.find(temp => temp.url === item[props.keyName])) return;
		// 			tempList.value.push({
		// 				...item,
		// 				url: item[props.keyName],
		// 				upload: true,
		// 				loading: false,
		// 				error: ''
		// 			});
		// 			return;
		// 		} else {
		// 			if (tempList.value.find(temp => temp.url === item)) return;
		// 			tempList.value.push({
		// 				url: item,
		// 				upload: true,
		// 				loading: false,
		// 				error: ''
		// 			});
		// 		}
		// 	});
		// } else {
		// 	if (!props.modelValue || tempList.value.find(item => item.url === props.modelValue)) return;
		// 	tempList.value.push({
		// 		url: props.modelValue,
		// 		upload: true,
		// 		loading: false,
		// 		error: ''
		// 	});
		// }
	});
	const chooseImage = () => {
		uni.chooseImage({
			count: props.limit,
			success: (res) => {
				res.tempFilePaths.forEach((item) => {
					if (tempList.value.includes(item) || tempList.value.length >= props.limit)
						return;
					tempList.value.push({
						url: item,
						upload: false,
						loading: false,
						error: ''
					});
				});
				if (props.autoUpload) {
					submit();
				}
			}
		});
	}
	const chooseVideo = () => {
		uni.chooseVideo({
			maxDuration: 60,
			success: (res) => {
				if (tempList.value.includes(res.tempFilePath) || tempList.value.length >= props.limit)
					return;
				tempList.value.push({
					url: res.tempFilePath,
					upload: false,
					loading: false,
					error: ''
				});
				if (props.autoUpload) {
					submit();
				}
			}
		});
	}
	const chooseFile = () => {
		uni.chooseFile({
			count: props.limit,
			success: (res) => {
				res.tempFiles.forEach((item) => {
					if (tempList.value.includes(item.path) || tempList.value.length >= props.limit)
						return;
					tempList.value.push({
						url: item.path,
						upload: false,
						loading: false,
						error: ''
					});
				});
				if (props.autoUpload) {
					submit();
				}
			}
		});
	}
	const selected = () => {
		if (props.disbale) return;
		switch (props.type) {
			case 'image':
				chooseImage();
				break;
			case 'video':
				chooseVideo();
				break;
			case 'file':
				chooseFile();
				break;
		}
	}
	const remove = (index) => {
		const item = tempList.value[index];
		if (props.remove) {
			props.remove(item, index).then(() => {
				tempList.value.splice(index, 1);
				if (item.upload) {
					update();
				}
			}).catch(() => {})
		} else {
			tempList.value.splice(index, 1);
			if (item.upload) {
				update();
			}
		}
	}
	const preview = (index) => {
		uni.previewImage({
			current: index,
			urls: tempList.value.map((item) => item.url)
		});
	}
	const upload = (i) => {
		const item = tempList.value[i];
		item.error = '';
		if (!item.upload) {
			item.loading = true;
			$http.upload('Upload/upload', {
				name: 'file',
				filePath: item.url,
				formData: props.data
			}).then((res) => {
				item.url = res.data.url;
				item.upload = true;
				update();
			}).catch((err) => {
				item.error = err.msg;
			}).finally(() => {
				item.loading = false;
			});
		}
	}
	const submit = () => {
		for (let i = 0; i < tempList.value.length; i++) {
			upload(i);
		}
	}
	const update = () => {
		const value = tempList.value.filter((item) => item.upload);
		if (value.length) {
			if (props.limit === 1) {
				if (props.keyName) {
					emit('update:modelValue', value[0]);
					emit('change', value[0]);
				} else {
					emit('update:modelValue', value[0]['url']);
					emit('change', value[0]['url']);
				}
			} else {
				if (props.keyName) {
					emit('update:modelValue', value);
					emit('change', value);
				} else {
					emit('update:modelValue', value.map((item) => item['url']));
					emit('change', value.map((item) => item['url']));
				}
			}
		} else {
			if (props.limit === 1) {
				emit('update:modelValue', '');
				emit('change');
			} else {
				emit('update:modelValue', []);
				emit('change');
			}
		}
	}
	const xUploadsRef = ref();
	onMounted(() => {
		nextTick(() => {
			height.value = (uni.getSystemInfoSync().windowWidth - props.margins - (4 * props.gap * (props
				.col -
				1))) / props.col;
		});
	});
	defineExpose({
		submit,
		selected
	});
</script>

<style lang="scss" scoped>
	.images-item {
		position: relative;

		.icons {
			padding: 2px;
			position: absolute;
			right: -1px;
			top: -1px;
			background-color: #f5f5f5;
			border-bottom-left-radius: 8px;
			border-top-right-radius: 8px;
			z-index: 10;
		}

		.loading {
			position: absolute;
			right: 0;
			top: 0;
			left: 0;
			bottom: 0;
			background-color: rgba(255, 255, 255, 0.4);
			border-radius: 8px;
			z-index: 100;
			display: flex;
			justify-content: center;
			align-items: center;

			&:before,
			.uni-icons {
				animation: spinner-cycle 3s linear infinite;
			}
		}

		.error {
			position: absolute;
			top: 50%;
			left: 50%;
			max-width: 80%;
			background-color: $uni-bg-color-mask;
			padding: 6px;
			border-radius: 8px;
			transform: translate(-50%, -50%);
			display: flex;
			flex-direction: column;
			justify-content: center;
			align-items: center;

			.message {
				padding: 2px 4px;
				border-radius: 4px;
				color: #fff;
			}
		}
	}

	@keyframes spinner-cycle {
		0% {
			transform: rotate(0deg);
		}

		100% {
			transform: rotate(360deg);
		}
	}
</style>